<script setup lang="ts">
import { getPageList } from '@/api/system/menu'
import { getMenuIdsByRoleId, saveRoleMenu } from '@/api/system/role'
import { notify } from '@/utils/element'

const state = reactive({
  visible: false,
  loading: false,
  submitting: false, // 提交中
  role: {} as SysRoleType, // 点击的那个角色对象
  menuList: [] as SysMenuType[],
  menuIds: [] as string[], // 角色拥有的ids
  checked: false, // 是否已全选
  expandAll: false, // 是否已展开
  query: {} as SysMenuQuery,
});

const { visible, loading, submitting, role, menuList, expandAll } = { ...toRefs(state) };

// 导出给父组件调用
defineExpose({
  open
});

/**
 * 打开窗口
 */
async function open(role: SysRoleType) {
  state.role = role;
  state.visible = true
  // 查询角色拥有的菜单ids
  await loadRoleMenuIds()
  // 显示树
  await loadMenuList()
  // 回显已勾选的权限
  await checkOldMenuNode()
}

/**
 * 关闭窗口
 */
function close() {
  if (state.submitting) return;
  state.menuIds = [];
  state.menuList = [];
  state.checked = false;
  state.expandAll = false;
  state.visible = false;
}

/**
 * 查询所有菜单项
 */
async function loadMenuList() {
  try {
    state.loading = true;
    const { data } = await getPageList(state.query);
    console.log('查询所有菜单项', data);

    state.menuList = data.results;
  } catch (error) {
  } finally {
    state.loading = false;
  }
}

/**
 * 查询角色原有权限菜单ids
 */
const treeRef = ref()
async function loadRoleMenuIds() {
  try {
    state.loading = true
    const { data } = await getMenuIdsByRoleId(state.role.id)
    console.log('查询角色原有权限菜单ids', data)
    state.menuIds = data.results
  } catch (error) {
  } finally {
    state.loading = false
  }
}

/**
 * 进行回显角色原的的权限菜单
 */
async function checkOldMenuNode() {
  const { menuIds } = state;
  menuIds.forEach(id => {
    // 获取节点对象
    const node = treeRef.value.getNode(id);
    // console.log('isLeft', id, node.isLeaf)
    // 根据节点对象，判断是否为子节点，是子节点则勾选，不是则不勾选 
    if (node && node.isLeaf) treeRef.value.setChecked(id, true);
  });
}

/**
 * 提交权限数据
 */
async function submitForm() {
  try {
    state.submitting = true;
    // 收集选中的菜单ids
    const checkedMenuIds = treeRef.value.getCheckedKeys();
    // console.log('checkedMenuIds', checkedMenuIds);
    // 收集半选中(父节点）的菜单id
    const parentIds = treeRef.value.getHalfCheckedKeys();
    // console.log('parentIds', parentIds);
    // 合并所有上面获取的菜单ids
    const menuIds = parentIds.concat(checkedMenuIds);
    await saveRoleMenu(state.role.id, menuIds);
    notify('分配权限成功!', { type: 'success' });
    state.submitting = false; // 防止关闭不了窗口
    // 关闭弹窗
    close();
  } catch (error) {
  } finally {
    state.submitting = false;
  }
}

</script>

<template>
  <el-dialog :title="`分配【${role.roleName}】权限`" v-model="visible" @close="close" draggable>
    <el-scrollbar max-height="460px">
      <el-tree ref="treeRef" class="min-h-300px" v-loading="loading" element-loading-text="正在加载中..." :data="menuList"
        node-key="id" show-checkbox highlight-current :props="{ children: 'children' }" :default-expand-all="expandAll">
        <template #default="{ node, data }">
          <span class="flex justify-center items-center">
            <!-- 一、二级菜单类型显示自定义图标 -->
            <SvgIcon v-if="[1, 2].includes(node.level)" :name="data.meta.icon" />
            <!-- 三级菜单显示`菜单`或`按钮`图标 -->
            <el-icon v-else>
              <el-icon v-if="data.type == 1">
                <ScaleToOriginal />
              </el-icon>
              <el-icon v-else-if="data.type == 2">
                <SwitchButton />
              </el-icon>
            </el-icon>
            <span class="ml3">{{ data.meta.title }}</span>
          </span>
        </template>
      </el-tree>
    </el-scrollbar>
    <template #footer>
      <div class="flex items-center justify-center">
        <el-button class="w-29" type="info" @click="close">取 消</el-button>
        <el-button class="w-29" type="primary" :loading="submitting" @click="submitForm">
          {{ submitting ? '正在提交 ...' : '提 交' }}
        </el-button>
      </div>
    </template>
  </el-dialog>
</template>

<style lang="scss" scoped></style>